#ifndef _LOADCOM_H_
#define _LOADCOM_H_


#include <dlcom/byunknown.hpp>
#include <dlcom/calldll.hpp>



MD_EXPORTS DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID* ppv);



typedef	HRESULT (OS_STDCALL *DefineDllGetClassObject)(REFCLSID rclsid,REFIID riid,LPVOID* ppv);
typedef HRESULT (OS_STDCALL *DefineDllCanUnloadNow)(void);
typedef	HRESULT (OS_STDCALL *DefineDllRegisterServer)(void);
typedef	HRESULT (OS_STDCALL *DefineDllUnregisterServer)(void);

 

class CComLoader : protected IImpModuleBase
{
public:
	DefineDllGetClassObject 	DllGetClassObject;
	DefineDllCanUnloadNow 		DllCanUnloadNow;
	DefineDllRegisterServer 	DllRegisterServer;
	DefineDllUnregisterServer 	DllUnregisterServer;
public: 
	inline CComLoader() : IImpModuleBase(_T("modulecom"))
	{
		
	} 
	virtual STFunDesc *GetFunDefs() 
	{ 
		static STFunDesc s_FunDefs[]= 
		{
			{ (char *)"DllGetClassObject",0},
			{ (char *)"DllCanUnloadNow",1},
			{ (char *)"DllRegisterServer",2},
			{ (char *)"DllUnregisterServer",3},
			{ (char *)"null",4}

		}; 
		return s_FunDefs;
	}
	virtual bool setfuncaddress(int i,void *p)
	{
		iosprintf("CComLoader->setfuncaddress")

		switch(i)
		{
			case 0:
				this->DllGetClassObject = (DefineDllGetClassObject)(p);
				break;
			case 1:
				this->DllCanUnloadNow =  (DefineDllCanUnloadNow)(p);
				break;
			case 2:
				this->DllRegisterServer = (DefineDllRegisterServer)(p);
				break;
			case 3:
				this->DllUnregisterServer = (DefineDllUnregisterServer)(p);
				break;
			default:
				break;
		}
		return true;

	}
	virtual ~CComLoader()
	{
		UnloadCom();
	}
public:
	BOOL LoadCom(const TCHAR* pModPathName)
	{

		iosprintf("CComLoader->LoadCom")
		memset(m_szModuleName,0,MAX_PATH);
		tstring_strcpy(m_szModuleName,pModPathName);

		int nRet = Load();
		if (nRet == -1)
		{
			iosprintf("CComLoader->Load fuc fail")
			memset(m_szModuleName,0,MAX_PATH);
			return FALSE;
		}
		

		if (DllGetClassObject == NULL) {

			iosprintf("CComLoader->DllGetClassObject error")
			return FALSE;
		}
			

		DllGetClassObject(CLSID_MDClassFactory, _uuidof(IComObjectFrameworkClassFactory), (void**)&m_pClassFactory);
		if(m_pClassFactory)
		{
			return TRUE;
		}

		UnloadCom();
		return FALSE;
	}
	virtual void UnloadCom()
	{
		if(m_pClassFactory)
			m_pClassFactory = INULL;
		UnLoad();
	}
	HRESULT CreateInstance(REFCLSID rclsid, IBase *prot, IBase *punkOuter, const IID& riid, void **ppv)
	{
		//*ppv = NULL;

		retrtpv(IsLoaded(), E_FAIL);
				
		_lComPtr<IClassFactory__> pClassFactory;
		if(SUCCEEDED(DllGetClassObject(rclsid, _uuidof(IClassFactory__), (void**)&pClassFactory)) && pClassFactory)
		{
			_lComPtr<IComObjectFrameworkClassFactory> pOFClassFactory = pClassFactory;
			if (pOFClassFactory) {
				iosprintf("pOFClassFactory->CreateInstance")
				return pOFClassFactory->CreateInstance(prot, punkOuter, riid, ppv);
			}	
		}
		return E_FAIL;
	}
	LONG GetCount()
	{
		if(m_pClassFactory)
			return m_pClassFactory->GetCount();
		return 0;
	}
	CLSID GetAt(INT nIndex)
	{
		if(m_pClassFactory)
			return m_pClassFactory->GetAt(nIndex);
		return GUID_NULL;
	}
	LPCSTR ProgIDFromCLSID(REFCLSID clsid)
	{
		if(m_pClassFactory)
			return m_pClassFactory->ProgIDFromCLSID(clsid);
		return "";
	}
	bool IsLoaded()
	{
		return IImpModuleBase::IsLoaded();
	}
protected:
	_lComPtr<IComObjectFrameworkClassFactory> m_pClassFactory;

};

#endif 